﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Mvc.Html;
using System.Text;
using App.Web.ViewModels;
using App.Core.Extensions;

namespace App.Web.Utility
{
    public static class HtmlHelpers
    {
        /// <summary>
        /// Custom helper method that renders a Error Message Box with the DIV Tag
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString ErrorMessageBox(this HtmlHelper helper, string message)
        {
            TagBuilder div = new TagBuilder("div");
            div.MergeAttribute("class", "ErrorMessageBox");
            div.InnerHtml = message;
            return MvcHtmlString.Create(div.ToString());
        }
        /// <summary>
        /// Custom helper method that renders a Info Message Box with the DIV Tag 
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="message"></param>
        /// <returns></returns>
        public static MvcHtmlString InfoMessageBox(this HtmlHelper helper, string message)
        {
            TagBuilder div = new TagBuilder("div");
            div.MergeAttribute("class", "InfoMessageBox");
            div.InnerHtml = message;
            return MvcHtmlString.Create(div.ToString());            
        }
        /// <summary>
        /// Gets Formatted Page Title
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="title"></param>
        /// <returns></returns>
        public static String GetPageTitle(this HtmlHelper helper, string title)
        {
            return string.Format("{0} - BdMarket24", title);
        }
        /// <summary>
        /// Creates a Script Tag for Java Script file
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="scriptName"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static MvcHtmlString JavaScript(this HtmlHelper helper, string scriptName, UrlHelper url)
        {
            String scriptPath = url.Content(String.Format("~/Scripts/{0}", scriptName));
            return MvcHtmlString.Create(String.Format("<script src=\"{0}\" type=\"text/javascript\"></script>", scriptPath));
        }
        public static MvcHtmlString ProductThumb(this HtmlHelper helper, ProductImageViewModel image, UrlHelper url, String altText = null)
        {
            if (image != null)
            {
                String imgUrl = ImageManager.GetProductImageUrl(image.Thumbnail, image.ProductID); //url.Content(String.Format("~{0}/{1}", AppConstants.Directories.PRODUCT_IMAGES, image.Thumbnail));
                return MvcHtmlString.Create(String.Format("<img src=\"{0}\" alt=\"{1}\" title=\"{1}\" />", imgUrl, altText.IsNullOrEmpty() ? image.Thumbnail : altText));
            }
            return null;
        }
        public static MvcHtmlString ProductThumb(this HtmlHelper helper, String fileName, int productID, String altText)
        {            
            String imgUrl = ImageManager.GetProductImageUrl(fileName, productID); //url.Content(String.Format("~{0}/{1}", AppConstants.Directories.PRODUCT_IMAGES, image.Thumbnail));
            return MvcHtmlString.Create(String.Format("<img src=\"{0}\" alt=\"{1}\" title=\"{1}\" />", imgUrl, altText.Replace("\"", String.Empty)));
        }
        /// <summary>
        /// Creates the company Logo Image tag
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="companyLogo"></param>
        /// <param name="companyID"></param>
        /// <param name="companyName"></param>
        /// <param name="url"></param>
        /// <returns></returns>
        public static MvcHtmlString LogoThumb(this HtmlHelper helper, String companyLogo, int companyID, String companyName, UrlHelper url)
        {
            companyName = String.Format("{0} Logo", companyName.Replace("\"", String.Empty));
            String imgUrl = ImageManager.GetCompanyLogoUrl(companyLogo, companyID);
            return MvcHtmlString.Create(String.Format("<img src=\"{0}\" alt=\"{1}\" title=\"{1}\"/>", imgUrl, companyName));
            //if (companyLogo.IsEmpty())
            //    return MvcHtmlString.Create(String.Format("<img src=\"{0}\" alt=\"{1}\" title=\"{1}\" />", url.Content(String.Format("~/Images/{0}", AppConstants.UI.NO_LOGO)), companyName));            
            //else
            //{
            //    String imgUrl = url.Content(String.Format("~{0}/{1}/{2}", AppConstants.Directories.COMPANY_LOGO, companyID, companyLogo));
            //    return MvcHtmlString.Create(String.Format("<img src=\"{0}\" alt=\"{1}\" title=\"{1}\"/>", imgUrl, companyName));
            //}            
        }
        /// <summary>
        /// Creates Category Breadcrumb for a Given Category ID
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="categoryID"></param>
        /// <param name="buildLink"></param>
        /// <returns></returns>
        public static MvcHtmlString GetCategoryBreadCrumb(this HtmlHelper helper, int categoryID, bool buildLink = false)
        {
            if (categoryID > 0)
            {
                //App.Domain.AppEntities context = new Domain.AppEntities();
                CategoryViewModel category = ApplicationCache.Categories.FirstOrDefault(P => P.ID == categoryID);
                if (category != null)
                {
                    List<String> names = new List<String>();
                    names.Add(category.Name);
                    while (category.ParentCategory != null)
                    {
                        names.Add(category.ParentCategory.Name);
                        category = category.ParentCategory;
                    }
                    StringBuilder sb = new StringBuilder(10);
                    for (int i = names.Count - 1; i >= 0; i--)
                    {
                        String format = " -> {0}";
                        if (sb.Length == 0)
                            format = "{0}";
                        
                            sb.AppendFormat(format, buildLink ?
                                helper.ActionLink(names[i], "category", "product", new { area = AppConstants.Area.PUBLIC, id = names[i].ToSeoUrl() }, null).ToHtmlString()                        
                                : names[i]);                        
                    }
                    return MvcHtmlString.Create(sb.ToString());
                }
            }
            return null;
        }
        /// <summary>
        /// Creates an Action Link for Administrator Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString AdminLink(this HtmlHelper helper, String linkText, String action, String controllerName)
        {
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.ADMIN }, null);
        }
        /// <summary>
        /// Creates an Action Link for Private Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString PrivateLink(this HtmlHelper helper, String linkText, String action, String controllerName)
        {            
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.PRIVATE }, null);
        }
        /// <summary>
        /// Creates an Action Link for Public Area
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="linkText"></param>
        /// <param name="action"></param>
        /// <param name="controllerName"></param>
        /// <returns></returns>
        public static MvcHtmlString PublicLink(this HtmlHelper helper, String linkText, String action, String controllerName)
        {
            return helper.ActionLink(linkText, action, controllerName, new { area = AppConstants.Area.PUBLIC }, null);
        }
        /// <summary>
        /// Creates a Product Details Link according to product info
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="productID"></param>
        /// <param name="productUrl"></param>
        /// <param name="linkText"></param>
        /// <returns></returns>
        public static MvcHtmlString ProductDetailsLink(this HtmlHelper helper, int productID, String productUrl, String linkText)
        {
            return new MvcHtmlString(String.Format("<a href=\"/product/details/{0}/{1}\">{2}</a>", productID, productUrl, linkText));
        }
        /// <summary>
        /// Returns Only the URL of the Product depending on whethear it is a company page or site page
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="companyKey"></param>
        /// <param name="productID"></param>
        /// <param name="productKey"></param>
        /// <returns></returns>
        public static String ProductDetailsUrl(this HtmlHelper helper, String companyKey, int productID, String productKey)
        {
            return companyKey.IsNullOrEmpty() ? String.Format("/product/details/{0}/{1}", productID, productKey)
                                            : String.Format("/{0}/{1}/{2}", companyKey, productID, productKey);
        }
        /// <summary>
        /// Renders a Tree Like Structure from given Categories Collection
        /// <para>This method is obsolete. Instead of this SelectableCategoryList is being used</para>
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="categories"></param>
        /// <param name="addSelectionRadio"></param>
        /// <param name="selectedCategory"></param>
        /// <returns></returns>
        public static MvcHtmlString RenderCategoryTree(this HtmlHelper helper, List<App.Web.ViewModels.CategoryViewModel> categories, bool addSelectionRadio, int selectedCategory = 0)
        {
            if (categories == null || categories.Count == 0)
                return null;

            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> parentCategories = (from P in categories where P.ParentID == null select P).ToList();
            foreach (CategoryViewModel parentCategory in parentCategories)
            {                
                sb.AppendFormat("<div class='TreeRootNodeContainer'>");
                sb.AppendFormat(addChildCategory(parentCategory, categories, addSelectionRadio, selectedCategory));
                sb.AppendFormat("</div>");                
            }
            sb.AppendFormat("<div class='clear'></div>");
            return MvcHtmlString.Create(sb.ToString());
        }

        public static MvcHtmlString RenderCategoryTreeForEdit(this HtmlHelper helper, List<App.Web.ViewModels.CategoryViewModel> categories, bool addSelectionRadio, int selectedCategory = 0)
        {
            if (categories == null || categories.Count == 0)
                return null;

            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> parentCategories = (from P in categories where P.ParentID == null select P).ToList();
            foreach (CategoryViewModel parentCategory in parentCategories)
            {
                sb.AppendFormat("<div class='TreeRootNodeContainer'>");
                sb.AppendFormat(addChildCategoryForEdit(parentCategory, categories, addSelectionRadio, selectedCategory));
                sb.AppendFormat("</div>");
            }
            sb.AppendFormat("<div class='clear'></div>");
            return MvcHtmlString.Create(sb.ToString());
        }

        /// <summary>
        /// Original Recursive Method to Generate the Tree Structure for Categories
        /// </summary>
        /// <param name="parentCategory"></param>
        /// <param name="categories"></param>
        /// <param name="addSelectionRadio"></param>
        /// <param name="selectedCategory"></param>
        /// <returns></returns>
        private static string addChildCategoryForEdit(CategoryViewModel parentCategory, List<CategoryViewModel> categories, bool addSelectionRadio, int selectedCategory = 0)
        {
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> children = (from P in categories where P.ParentID == parentCategory.ID select P).ToList();
            String checkedString = String.Empty;
            if (parentCategory.ID == selectedCategory)
                checkedString = " checked='checked' "; 

            if (children == null || children.Count == 0)            
            {
                ////TODO: Need check and fix this category generation.
                //if (parentCategory.ParentID == null)
                //{
                //    sb.AppendFormat("<div class='TreeParentNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' {2}/><label for='rdnCategory_{0}' class='TreeTitle'>{1}</label></div>", parentCategory.ID, parentCategory.Name, checkedString);
                //}
                if (addSelectionRadio && parentCategory.PropertyDefinition != null)
                    sb.AppendFormat("<div class='TreeChildNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' {2}/><label for='rdnCategory_{0}' class='TreeTitle'>{1}</label></div>", parentCategory.ID, parentCategory.Name, checkedString);
                    //sb.AppendFormat("<div class='TreeChildNode'>{0}</div>", parentCategory.Name);
                else if (addSelectionRadio && parentCategory.PropertyDefinition.IsNullOrEmpty())
                    sb.AppendFormat("<div class='TreeChildNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' {2}/><label for='rdnCategory_{0}'>{1}</label></div>", parentCategory.ID, parentCategory.Name, checkedString);
                    //sb.AppendFormat("<div class='TreeChildNode'>{0}</div>", parentCategory.Name);
                return sb.ToString();
            }
            else
            {   
                if (parentCategory.ParentID == null)
                    sb.AppendFormat("<div class='TreeParentNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' {2}/><label for='rdnCategory_{0}' class='TreeTitle'>{1}</label>", parentCategory.ID, parentCategory.Name, checkedString); //sb.AppendFormat("<div class='TreeParentNode'><span class='TreeTitle'>{0}</span>", parentCategory.Name);
                else
                {
                    sb.AppendFormat("<div class='TreeParentNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}' {2}/><label for='rdnCategory_{0}' class='TreeTitle'>{1}</label>", parentCategory.ID, parentCategory.Name, checkedString); //sb.AppendFormat("<div class='TreeParentNode'>{0}", parentCategory.Name);
                }
                foreach (CategoryViewModel child in children)
                {
                    sb.Append(addChildCategoryForEdit(child, categories, addSelectionRadio, selectedCategory));
                }
                sb.AppendFormat("</div>");
                
                return sb.ToString();
            }
        }
        /// <summary>
        /// Regnders a Category Tree Menu by an Specific Parent Category ID for Site's Top Navigation
        /// <para>This method is obsolete.</para>
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="parentCategoryID"></param>
        /// <param name="addSelectionRadio"></param>
        /// <returns></returns>
        public static MvcHtmlString RenderCategoryMenu(this HtmlHelper helper, int parentCategoryID, bool addSelectionRadio)
        {
            List<CategoryViewModel> allCategories = ApplicationCache.Categories;
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> parentCategories = (from P in allCategories where P.ParentID == parentCategoryID select P).ToList();
            foreach (CategoryViewModel parentCategory in parentCategories)
            {
                sb.AppendFormat("<div class='TreeRootNodeContainer'>");
                sb.AppendFormat(addChildCategoryForMenu(parentCategory, allCategories, addSelectionRadio));
                sb.AppendFormat("</div>");
            }
            sb.AppendFormat("<div class='clear'></div>");
            return MvcHtmlString.Create(sb.ToString());
        }
        
        /// <summary>
        /// Creates an Album Like HTML Structure required to work with Lightbox jQuery Plugin
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="productImages"></param>
        /// <returns></returns>
        public static MvcHtmlString GetProductImagesLightboxHtml(this HtmlHelper helper, List<ViewModels.ProductImageViewModel> productImages)
        {
            int i = 0;
            StringBuilder sb = new StringBuilder();
            foreach(App.Web.ViewModels.ProductImageViewModel image in productImages)
            {
                sb.AppendFormat("<div class=\"{0}\">", getCssClassforAlbumItem(i, productImages.Count));
                sb.AppendFormat("<a href=\"{0}\" rel=\"lightbox[ProductAlbum]\" title=\"Click on the Right/Left side of the image to move Forward/Reverse.\"><img src=\"{1}\" alt=\"Image {2} 0f {3} thumb\" /></a>"
                    , ImageManager.GetProductImageUrl(image.Picture, image.ProductID)
                    , ImageManager.GetProductImageUrl(image.Thumbnail, image.ProductID)
                    , i + 1
                    , productImages.Count);
                ///Following Setup Does Not work with lightbox
                //sb.AppendFormat("<a href=\"{0}\" title=\"Click on the Right/Left side of the image to move Forward/Reverse.\"><img src=\"{1}\" alt=\"Image {2} 0f {3} thumb\" /></a>"
                //    , ImageManager.GetProductImageUrl(image.Picture, image.ProductID)
                //    , ImageManager.GetProductImageUrl(image.Thumbnail, image.ProductID)
                //    , i + 1
                //    , productImages.Count);
  		            
  		        sb.Append("</div>");
                //<img src="@(AppConstants.Directories.PRODUCT_IMAGES + "/" + image.Thumbnail)" alt="" title="" />                
                i++;
            }
            return MvcHtmlString.Create(sb.ToString());
        }

        #region Private Methods
        /// <summary>
        /// Gets the CSS Class for an Album Item according to the Lightbox jQuery Plugin Specification
        /// </summary>
        /// <param name="i"></param>
        /// <param name="itemCount"></param>
        /// <returns></returns>
        private static string getCssClassforAlbumItem(int i, int itemCount)
        {
            if (i == 0 & itemCount > 1)
                return "single first";
            else if (itemCount - 1 == i)
                return "single last";
            else
                return "single";
        }
        /// <summary>
        /// Original Recursive Method to Generate the Tree Structure for Categories
        /// </summary>
        /// <param name="parentCategory"></param>
        /// <param name="categories"></param>
        /// <param name="addSelectionRadio"></param>
        /// <param name="selectedCategory"></param>
        /// <returns></returns>
        private static string addChildCategory(CategoryViewModel parentCategory, List<CategoryViewModel> categories, bool addSelectionRadio, int selectedCategory = 0)
        {
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> children = (from P in categories where P.ParentID == parentCategory.ID select P).ToList();
            if (children == null || children.Count == 0)
            //if (parentCategory.PropertyDefinition != null)
            {
                if (addSelectionRadio && parentCategory.PropertyDefinition != null)
                {
                    if (selectedCategory == parentCategory.ID)
                        sb.AppendFormat("<div class='TreeChildNode'><input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label></div>", parentCategory.ID, parentCategory.Name);
                    else
                        sb.AppendFormat("<div class='TreeChildNode'><input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label></div>", parentCategory.ID, parentCategory.Name);
                }
                else
                    sb.AppendFormat("<div class='TreeChildNode'>{0}</div>", parentCategory.Name);
                return sb.ToString();
            }
            else
            {
                ///Following Line Should be Disabled if line 109 Disabled
                //if (children != null && children.Count > 0)
                {
                    if (parentCategory.ParentID == null)
                        sb.AppendFormat("<div class='TreeParentNode'><span class='TreeTitle'>{0}</span>", parentCategory.Name);
                    else
                    {
                        sb.AppendFormat("<div class='TreeParentNode'>{0}", parentCategory.Name);
                    }
                    foreach (CategoryViewModel child in children)
                    {
                        sb.Append(addChildCategory(child, categories, addSelectionRadio, selectedCategory));
                    }
                    sb.AppendFormat("</div>");
                }
                return sb.ToString();
            }
        }
        /// <summary>
        /// The Recursive Method that Creates the Category Menu Tree Structure for Top Navigation
        /// <para>This method is obsolete.</para>
        /// </summary>
        /// <param name="parentCategory"></param>
        /// <param name="allCategories"></param>
        /// <param name="addSelectionRadio"></param>
        /// <returns></returns>
        private static string addChildCategoryForMenu(CategoryViewModel parentCategory, List<CategoryViewModel> allCategories, bool addSelectionRadio)
        {
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> children = (from P in allCategories where P.ParentID == parentCategory.ID select P).ToList();            
            if (children == null || children.Count == 0)
                sb.AppendFormat("<div class='TreeParentNode'><a href='{0}'>{1}</a></div>", GetCategoryListLink(parentCategory.Name), parentCategory.Name);            
            else
            {
                sb.AppendFormat("<div class='TreeParentNode'>{0}", parentCategory.Name);
                foreach (CategoryViewModel child in children)
                {
                    sb.Append(addChildCategoryForMenu(child, allCategories, addSelectionRadio));
                }
                sb.AppendFormat("</div>");
            }    
            
            return sb.ToString();            
        }
        public static string GetCategoryListLink(String categoryName)
        {
            return String.Format("/product/category/{0}", categoryName.ToSeoUrl());
        }
        /// <summary>
        /// Gets Formated Data for Display Purpose
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public static String FormatData(this HtmlHelper helper, object data)
        {
            return WebUtil.FormatData(data);
        }
        #endregion Private Methods

        /// <summary>
        /// Gets Completed External Absolute URL
        /// </summary>
        /// <param name="url"></param>
        /// <returns></returns>
        public static String GetCompleteUrl(this HtmlHelper helper, String url)
        {
            return url.ToLower().StartsWith("http://") ? url : String.Format("http://{0}", url);
        }

        /// <summary>
        /// Creates Company Address Html to Show in the Company Profile Page
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="address"></param>
        /// <param name="district"></param>
        /// <param name="country"></param>
        /// <param name="phone"></param>
        /// <param name="fax"></param>
        /// <param name="email"></param>
        /// <param name="web"></param>
        /// <returns></returns>
        public static MvcHtmlString BuildCompanyAddress(this HtmlHelper helper, String address, String district, String country, String phone, String fax, String email, String web)
        {
            StringBuilder sb = new StringBuilder(10);
            sb.AppendFormat("{0}<br/>", address.HtmlEncode());
            sb.AppendFormat("{0}, {1}<br />", district.HtmlEncode(), country.HtmlEncode());            
            sb.AppendFormat("Phone: {0}", phone.HtmlEncode());
            if(!fax.IsEmpty())
                sb.AppendFormat(", Fax: {0}", fax.HtmlEncode());
            if(!email.IsEmpty())
                sb.AppendFormat("<br />Email: {0}", email.HtmlEncode());
            if(!web.IsEmpty())
                sb.AppendFormat("<br/>Web Site: <a href='{0}' target='_blank'>{0}</a>", helper.GetCompleteUrl(web));

            return MvcHtmlString.Create(sb.ToString());
        }
        /// <summary>
        /// Creates a Company's Product Details Link Htlm Anchor tag
        /// </summary>
        /// <param name="helper"></param>
        /// <param name="companyKey"></param>
        /// <param name="productID"></param>
        /// <param name="productKey"></param>
        /// <param name="linkText"></param>
        /// <returns></returns>
        public static MvcHtmlString CompanyProductDetailsLink(this HtmlHelper helper, String companyKey, int productID, String productKey, String linkText)
        {
            return new MvcHtmlString(String.Format("<a href=\"/{0}/{1}/{2}\">{3}</a>", companyKey, productID, productKey, linkText));
        }

        public static MvcHtmlString GenerateCategoryMenu(this HtmlHelper helper, int parentCategoryID)
        {
            StringBuilder sb = new StringBuilder(10);
            int rowCounter = 0;
            bool hasColumnClosed = true;
            var firstLevelChildren = from P in ApplicationCache.Categories where P.ParentID == parentCategoryID && P.PropertyDefinition.IsNullOrEmpty() select P;
            foreach (CategoryViewModel firstLevelChild in firstLevelChildren)
            {
                if (rowCounter > 0 && rowCounter % ConfigReader.NumberOfRowsInCategoryMenu == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                if (rowCounter == 0)
                {
                    sb.AppendFormat("<div class='category-column'><div class='first-child' style='margin-top:0px;'>");
                    hasColumnClosed = false;
                }
                else
                    sb.Append("<div class='first-child'>");
                sb.AppendFormat("<a href='/product/category/{0}'>{1}</a></div>", firstLevelChild.UrlName, firstLevelChild.Name);
                rowCounter++;
                if (rowCounter % ConfigReader.NumberOfRowsInCategoryMenu == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                var secondLevelChildren = from P in ApplicationCache.Categories where P.ParentID == firstLevelChild.ID select P;
                foreach (CategoryViewModel secondLevelChild in secondLevelChildren)
                {
                    if (rowCounter == 0)
                    {
                        sb.AppendFormat("<div class='category-column'>");
                        hasColumnClosed = false;
                    }
                    sb.AppendFormat("<div class='second-child'><a href='/product/category/{0}'>{1}</a></div>", secondLevelChild.UrlName, secondLevelChild.Name);
                    rowCounter++;
                    if (rowCounter % ConfigReader.NumberOfRowsInCategoryMenu == 0)
                    {
                        sb.Append("</div>");
                        hasColumnClosed = true;
                        rowCounter = 0;
                    }
                }            
            }
            if (!hasColumnClosed)
                sb.Append("</div>");

            return new MvcHtmlString(sb.ToString());
        }

        public static MvcHtmlString SelectableCategoryList(this HtmlHelper helper, List<App.Web.ViewModels.CategoryViewModel> categories, bool addSelectionRadioForAllParents, int selectedCategory = 0)
        {
            if (categories == null || categories.Count == 0)
                return null;
            StringBuilder sb = new StringBuilder();
            List<CategoryViewModel> parentCategories = (from P in categories where P.ParentID == null select P).ToList();
            int rowCounter = 0;
            bool hasColumnClosed = true;            
            foreach (CategoryViewModel parentCategory in parentCategories)
            {
                if (rowCounter > 0 && rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                if (rowCounter == 0)
                {
                    sb.AppendFormat("<div class='category-column'><div class='parent-category' style='margin-top:0px;'>");
                    hasColumnClosed = false;
                }
                else
                    sb.Append("<div class='parent-category'>");
                if (addSelectionRadioForAllParents)
                {
                    if (selectedCategory == parentCategory.ID)
                        sb.AppendFormat("<input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", parentCategory.ID, parentCategory.Name);
                    else
                        sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", parentCategory.ID, parentCategory.Name);
                    //sb.AppendFormat();
                }
                else
                    sb.AppendFormat("{0}", parentCategory.Name);
                sb.Append("</div>");
                rowCounter++;
                if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                {
                    sb.Append("</div>");
                    hasColumnClosed = true;
                    rowCounter = 0;
                }
                var firstLevelChildren = from P in ApplicationCache.Categories where P.ParentID == parentCategory.ID && P.PropertyDefinition.IsNullOrEmpty() select P;
                foreach (CategoryViewModel firstLevelChild in firstLevelChildren)
                {
                    if (rowCounter > 0 && rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                    {
                        sb.Append("</div>");
                        hasColumnClosed = true;
                        rowCounter = 0;
                    }
                    if (rowCounter == 0)
                    {
                        sb.AppendFormat("<div class='category-column'><div class='first-child'>");
                        hasColumnClosed = false;
                    }
                    else
                        sb.Append("<div class='first-child'>");
                    if (addSelectionRadioForAllParents)
                    {
                        if (selectedCategory == firstLevelChild.ID)
                            sb.AppendFormat("<input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", firstLevelChild.ID, firstLevelChild.Name);
                        else
                            sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", firstLevelChild.ID, firstLevelChild.Name);                        
                    }
                    else
                        sb.AppendFormat("{0}", firstLevelChild.Name);
                    sb.Append("</div>");
                    rowCounter++;
                    if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                    {
                        sb.Append("</div>");
                        hasColumnClosed = true;
                        rowCounter = 0;
                    }
                    var secondLevelChildren = from P in ApplicationCache.Categories where P.ParentID == firstLevelChild.ID select P;
                    if (!addSelectionRadioForAllParents)
                    {
                        foreach (CategoryViewModel secondLevelChild in secondLevelChildren)
                        {
                            if (rowCounter == 0)
                            {
                                sb.AppendFormat("<div class='category-column'>");
                                hasColumnClosed = false;
                            }
                            sb.AppendFormat("<div class='second-child'>");
                            ///Product Cannot be entered under an empty category definition
                            if (secondLevelChild.PropertyDefinition.IsNullOrEmpty())
                                sb.AppendFormat(secondLevelChild.Name);
                            else if (selectedCategory == secondLevelChild.ID)
                                sb.AppendFormat("<input checked='checked' name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", secondLevelChild.ID, secondLevelChild.Name);
                            else
                                sb.AppendFormat("<input name='rdnCategory' id='rdnCategory_{0}' type='radio' value='{0}'/><label for='rdnCategory_{0}'>{1}</label>", secondLevelChild.ID, secondLevelChild.Name);
                            sb.Append("</div>");
                            rowCounter++;
                            if (rowCounter % ConfigReader.NumberOfRowsInCategorySelection == 0)
                            {
                                sb.Append("</div>");
                                hasColumnClosed = true;
                                rowCounter = 0;
                            }
                        }
                    }
                }
            }
            if (!hasColumnClosed)
                sb.Append("</div>");
            return new MvcHtmlString(sb.ToString());
        }
    }
}